ReflectLevel.prototype = new Sprite();
ReflectLevel.prototype = new Level ();
/**
*@class ReflectLevel
*@augments Level, Sprite 
*@param name nazov levelu
*@param levelOrd  poradove cislo levelu
*@param type typ levelu
*@description Zakladna trieda pre ReflectLevel
*/
function ReflectLevel(name, levelOrd, type){
    Sprite.apply(this); 
    Level.apply(this);
    this.name = name;
    this.levelOrd = levelOrd;
    this.type = type;
    
    //properties
    this.debug = false;
    this.laser = null;
    this.laserDraw = null;
    this.goal = null;
    this.selectedMirror = null;
    this.mirrors = new Array();
    this.sockPoints = new Array();
    this.solved = false;
    this.clickedXY = new Point(0,0);
    
    //methods assiciation
    
    this.init = LevelInit;
    this.drawLaser = drawLaser;
    this.getIndexOf = getIndexOf;
    this.isSolved = isSolved;
}
/**
 * @class ReflectLevel
 * @description Metoda sluziaca k inicializacii levelu
 */
function LevelInit (){
    var laserPNG = new BitmapData("pictures/laser.png");
    this.laser = new Bitmap(laserPNG);
    this.laser.y = MainContainerHeight/2-20;
    this.addChild(this.laser);
    
    var goalPNG = new BitmapData("pictures/goal.png");
    this.goal = new Bitmap(goalPNG);
    this.goal.x = MainContainerWidth - 40;
    this.goal.y = MainContainerHeight/2 - 20;
    this.addChild(this.goal);
    
    var center = new Point(MainContainerWidth/2,MainContainerHeight/2);
    
    for (var i = 0; i < 6; i++){
        var initPoint = new Point (-150,0);
        var v = Geometry.rotate(initPoint,-60*i);
        this.sockPoints[i] = Geometry.vectorAddition(v,center);
    }
    
    var beamPath = [[new Point (20,MainContainerHeight/2),this.sockPoints[0],this.sockPoints[2]],
    [this.sockPoints[2],this.sockPoints[1],this.sockPoints[3]],
    [this.sockPoints[0],this.sockPoints[2],this.sockPoints[1]],
    [this.sockPoints[1],this.sockPoints[3],this.sockPoints[4]],
    [this.sockPoints[3],this.sockPoints[4],this.sockPoints[5]],
    [this.sockPoints[4],this.sockPoints[5],new Point (MainContainerWidth - 20,MainContainerHeight/2)]];
    
    for (i = 0; i<6; i++){
        var vecU = Geometry.pointsToVector(beamPath[i][1], beamPath[i][0]);
        var vecV = Geometry.pointsToVector(beamPath[i][1], beamPath[i][2]);
        var beamAngle = Geometry.vectorAngle(vecV,vecU);
        var nVect = Geometry.vectorAddition(Geometry.unitVector(vecU),Geometry.unitVector(vecV));
        this.mirrors[i] = new Mirror(this.sockPoints[i].x,this.sockPoints[i].y,nVect,i);
        this.mirrors[i].init();
        this.mirrors[i].addEventListener(MouseEvent.CLICK,mouseClick);
        this.mirrors[i].addEventListener(MouseEvent.MOUSE_OVER,mouseOver);
        this.mirrors[i].addEventListener(MouseEvent.MOUSE_OUT,mouseOut);
        this.addChild(this.mirrors[i]);
    }
    
    for (i = 0; i<30; i++){
        var rand1 = Math.floor(Math.random()*5);
        var rand2 = Math.floor(Math.random()*5);
        switchMirrors(this, rand1, rand2);
    }
    this.laserDraw = new Sprite();
    this.addChild (this.laserDraw);
    this.drawLaser();
    
    this.addChild(this.goal);
}
/**
 * @class ReflectLevel
 * @description Metoda zistujuca ci je level uz vyrieseny
 * @return True ak je level vyrieseny inak false
 */
function isSolved (){
    var result = 0;
    for (var i = 0; i < 6;i++){
        result += this.mirrors[i].id*Math.pow(10,i);
    }   
    if (result == 543210 || result == 542310)
        return true;
    
    return false;
}
/**
 * @class ReflectLevel
 * @param mirror Instancia triedy zrkadlo
 * @description Metoda zistujuca index zrkadla v poli zrkadiel
 * @return Index zrkadla ak existuje inak -1
 */
function getIndexOf (mirror){
    for (var i = 0; i < 6; i++){
        if (this.mirrors[i] == mirror)
            return i;
    }
    return -1;
}
/**
 * @class ReflectLevel
 * @description Metoda na vykreslovanie laseru
 */
function drawLaser (){
    this.laserDraw.graphics.clear();
    var from = new Point(20,MainContainerHeight/2);
    this.laserDraw.graphics.lineStyle(2,0xff0000);
    this.laserDraw.graphics.moveTo (from.x,from.y);
    var lineLaser = new Line(from, new Point (0,1),null);
    var lineMirror;
    var currMirror = null;
    var usedMirrors = new Array();
    do{
        currMirror = null; 
        for (var i = 0; i < 6;i++){
            var mirrorI =this.mirrors[i]
            
            if (usedMirrors.indexOf(mirrorI) != -1 )
                continue;
            if (usedMirrors.length > 0){
                var lastMirrorLine = new Line (new Point(usedMirrors[usedMirrors.length-1].x,usedMirrors[usedMirrors.length-1].y),usedMirrors[usedMirrors.length-1].nVect);
                if ((lastMirrorLine.a*mirrorI.x+lastMirrorLine.b*mirrorI.y+lastMirrorLine.c)<0)
                    continue;
            }
            lineMirror = new Line (new Point(mirrorI.x,mirrorI.y),mirrorI.nVect);
            var intersection = Geometry.intersectionPoint(lineLaser, lineMirror);
            if (intersection != null && Geometry.layAmong(intersection, mirrorI.getEdges()[0], mirrorI.getEdges()[1])){
                currMirror = mirrorI;
                usedMirrors.push(mirrorI);
                break;
            }
        }
        if (currMirror != null){
            from = currMirror.nVect;
            this.laserDraw.graphics.lineTo(intersection.x,intersection.y);
            if (Geometry.scalarProduct(from, new Point(-lineLaser.b,lineLaser.a))<= 0){    
                break;
            }
            lineLaser = new Line (new Point(currMirror.x,currMirror.y),Geometry.getAxiallySymmetricVector(new Point(lineLaser.a,lineLaser.b),currMirror.nVect),null);
        }
        else{
            var boundingLines = [new Line(new Point (0,0),new Point(0,1),null),
                                    new Line(new Point (0,0),new Point(1,0),null),
                                    new Line (new Point (MainContainerWidth,MainContainerHeight),new Point(0,1),null),
                                    new Line (new Point (MainContainerWidth,MainContainerHeight),new Point(1,0),null)];
            var boundsOfLines = [[new Point(0,0),new Point(MainContainerWidth,0)],
                                 [new Point(0,0),new Point(0,MainContainerHeight)],
                                 [new Point(MainContainerWidth,MainContainerHeight),new Point(0,MainContainerHeight)],
                                 [new Point(MainContainerWidth,MainContainerHeight),new Point(MainContainerWidth,0)]];                            
            var inter1 = null;
            var inter2 = null;
            for (var j = 0;j < 4;j++){
                var intersection = Geometry.intersectionPoint(lineLaser, boundingLines[j]);
                if (intersection != null && Geometry.layAmong(intersection, boundsOfLines[j][0], boundsOfLines[j][1])){
                        if (inter1 == null)
                            inter1 = intersection;
                        else
                            inter2 = intersection;
                }
            }    
         if (this.debug){
              this.laserDraw.graphics.moveTo(inter1.x, inter1.y);
              this.laserDraw.graphics.lineTo(inter2.x, inter2.y);    
          }
          else{
              var vectToInter = Geometry.pointsToVector(new Point(usedMirrors[usedMirrors.length-1].x,usedMirrors[usedMirrors.length-1].y),inter1);
              if (Geometry.scalarProduct(from, vectToInter)> 0){
                  this.laserDraw.graphics.lineTo(inter1.x, inter1.y);    
              }
              else{
                  this.laserDraw.graphics.lineTo(inter2.x, inter2.y);    
              }
          }
        }
    }
    while (currMirror != null)
    if (this.debug){  
        for (var i = 0;i <6;i++){
            //  normala
            this.laserDraw.graphics.lineStyle(2,0xff);
            this.laserDraw.graphics.moveTo (this.sockPoints[i].x,this.sockPoints[i].y);
            this.laserDraw.graphics.lineTo(this.sockPoints[i].x+this.mirrors[i].nVect.x*100,
                this.sockPoints[i].y+this.mirrors[i].nVect.y*100);
            // smerova priamka laseru
            this.laserDraw.graphics.lineStyle(2,0x0);
            var boundingLines = [new Line(new Point (0,0),new Point(0,1),null),
            new Line(new Point (0,0),new Point(1,0),null),
            new Line (new Point (MainContainerWidth,MainContainerHeight),new Point(0,1),null),
            new Line (new Point (MainContainerWidth,MainContainerHeight),new Point(1,0),null)];
            var boundsOfLines = [[new Point(0,0),new Point(MainContainerWidth,0)],
            [new Point(0,0),new Point(0,MainContainerHeight)],
            [new Point(MainContainerWidth,MainContainerHeight),new Point(0,MainContainerHeight)],
            [new Point(MainContainerWidth,MainContainerHeight),new Point(MainContainerWidth,0)]];
          
            var inter1 = null;
            var inter2 = null;
            var lineMirror = new Line (new Point(this.mirrors[i].x,this.mirrors[i].y),this.mirrors[i].nVect);
            for (var j = 0;j < 4;j++){
                var intersection = Geometry.intersectionPoint(lineMirror, boundingLines[j]);
                if (intersection != null && Geometry.layAmong(intersection, boundsOfLines[j][0], boundsOfLines[j][1])){
                    if (inter1 == null)
                        inter1 = intersection;
                    else
                        inter2 = intersection;
                }
            }
            this.laserDraw.graphics.moveTo(inter1.x, inter1.y);
            this.laserDraw.graphics.lineTo(inter2.x, inter2.y);    
        }
    }
}


/**
 * @class ReflectLevel
 * @event mouseClick
 * @description Metoda obsluhujuca even MouseClick
 */
function mouseClick (event){
    var owner = event.target.parent;
    if (owner.selectedMirror == null){
        owner.selectedMirror = event.target;
        event.target.graphics.lineStyle(2,0xff);
        event.target.graphics.moveTo(-20, -20);
        event.target.graphics.lineTo(-20, 20);
        event.target.graphics.lineTo(20, 20);
        event.target.graphics.lineTo(20, -20);
        event.target.graphics.lineTo(-20, -20);   
    }
    else if (owner.selectedMirror == event.target)
    {
        owner.selectedMirror = null;
        event.target.graphics.clear();
    }
    else{
        var I1 = owner.getIndexOf (owner.selectedMirror);
        var I2 = owner.getIndexOf (event.target);
        switchMirrors(owner, I1, I2);
        owner.selectedMirror = null;
        owner.drawLaser();
    }
    if (owner.isSolved()){
        alert ('gratulujem!!');
    }
}
/**
 * @class ReflectLevel
 * @event mouseOver
 * @description Metoda obsluhujuca even MouseOver
 */
function mouseOver (event){
    event.target.graphics.lineStyle(2,0x00ff00);
    event.target.graphics.moveTo(-20, -20);
    event.target.graphics.lineTo(-20, 20);
    event.target.graphics.lineTo(20, 20);
    event.target.graphics.lineTo(20, -20);
    event.target.graphics.lineTo(-20, -20);
}
/**
 * @class ReflectLevel
 * @event mouseOut
 * @description Metoda obsluhujuca even MouseOut
 */
function mouseOut (event){
    var owner = event.target.parent;
    if (event.target != owner.selectedMirror)
        event.target.graphics.clear();
    else{
        event.target.graphics.lineStyle(2,0xff);
        event.target.graphics.moveTo(-20, -20);
        event.target.graphics.lineTo(-20, 20);
        event.target.graphics.lineTo(20, 20);
        event.target.graphics.lineTo(20, -20);
        event.target.graphics.lineTo(-20, -20);   
    }
}
/**
 * @class ReflectLevel
 * @param owner Vlastnik zrkadiel ktore sa idu vymienat
 * @param 
 * @description Metoda obsluhujuca even MouseClick
 */
function switchMirrors(owner,m1,m2){
        if (m1 == m2)
            return;
        var hlp = owner.mirrors[m1];
        owner.mirrors[m1] = owner.mirrors[m2];
        owner.mirrors[m2] = hlp;
        
        owner.mirrors[m1].x = owner.mirrors[m1].x ^ owner.mirrors[m2].x;
        owner.mirrors[m2].x = owner.mirrors[m1].x ^ owner.mirrors[m2].x;
        owner.mirrors[m1].x = owner.mirrors[m1].x ^ owner.mirrors[m2].x;
        
        owner.mirrors[m1].y = owner.mirrors[m1].y ^ owner.mirrors[m2].y;
        owner.mirrors[m2].y = owner.mirrors[m1].y ^ owner.mirrors[m2].y;
        owner.mirrors[m1].y = owner.mirrors[m1].y ^ owner.mirrors[m2].y;
}